#include <os/semaphore.h>
#include <os/memcache.h>
#include <os/schedule.h>
#include <os/task.h>
#include <os/debug.h>

// create semaphore
semaphore_t *SemaphoreAlloc(int val)
{
    semaphore_t *semap = KMemAlloc(sizeof(semaphore_t));

    if (semap != NULL)
    {
        SemaphoreInit(semap, val);
        return semap;
    }
    return NULL;
}

// free semaphore
int SemaphoreFree(semaphore_t *semap)
{
    if (semap != NULL)
    {
        SemaphoreDestroy(semap);
        KMemFree(semap);
        return 0;
    }
    return -1;
}

// down a semaphore
void _SemaphoreDown(semaphore_t *semap)
{
    list_add_tail(&cur_task->list, &semap->waiter.wait_list);
    TASK_INTO_WAITLIST(cur_task);
    MutexlockUnlock(&semap->lock);
    TaskBlock(TASK_WAITTING);
}

void _SemaphoreUp(semaphore_t *semap)
{
    task_t *waiter = list_first_owner(&semap->waiter.wait_list, task_t, list);
    if (waiter != NULL)
    {
        list_del(&waiter->list);
        TASK_EXIT_WAITLIST(waiter);
        // semaphore down
        AtomicDec(&semap->counter);
        MutexlockUnlock(&semap->lock);
        TaskUnBlock(waiter);
    }
}
